package com.hx.zhg.util;

import org.apache.commons.lang.ArrayUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * Created by zhenghegong on 2019/1/29.
 */
public class RSAUtil {

    /**
     * 指定加密算法为RSA
     */
    private static final String ALGORITHM = "RSA";

    /**
     * 指定公钥存放文件
     */
    public static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkDmfLUhV8wfmQ0BBYBIzl2YL7\n" +
            "+U3kVZQlCtnDsC5HveJjlKRYD0Pse/szXSnwPtg2w44qpsK5F7yfkIcjkJtkv/cX\n" +
            "g8j+TCWRmoFs6jhNsjczM2LAwnxdpm3nYzqK0QwrbfvCbxGhcB5mk9H8ktpL3Kzo\n" +
            "DbDPlSID/gTA3Qs6DwIDAQAB";

    /**
     * 指定私钥存放文件
     */
    public static String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKQOZ8tSFXzB+ZDQ\n" +
            "EFgEjOXZgvv5TeRVlCUK2cOwLke94mOUpFgPQ+x7+zNdKfA+2DbDjiqmwrkXvJ+Q\n" +
            "hyOQm2S/9xeDyP5MJZGagWzqOE2yNzMzYsDCfF2mbedjOorRDCtt+8JvEaFwHmaT\n" +
            "0fyS2kvcrOgNsM+VIgP+BMDdCzoPAgMBAAECgYBCpt+giU7VivFb1kxtlhuwXniK\n" +
            "6rSsqeAwVII4sOF8oDbUAlXquPj9oTljmtwpET9CsJyX03yVOoGVymA9IMkgtPJ0\n" +
            "Tvxvol8YKCsDqVYWTqYX5iPGrvHyDFBy4Lu6CSEjDRj3l9f44juJI4AlR0OvvLtq\n" +
            "zNaCzLRZx40fyqALUQJBANaST6/t1Nb+t6BxOYvrtrFQHTsC2+5gUmZQ1Jb1ilYD\n" +
            "XL04CPtoruXIjDPu+UlekC51Wpy+PKdIIltBSOBEgfMCQQDDu0MS3QpbJY7a3K/b\n" +
            "Cs9Mxxoo83OoM/SnSxjTFxMpzGgF2qiKms6PckLCtpD+XUOlphs8XKplfCI/TQDO\n" +
            "dFJ1AkBCaFfnUAkuXPkB2+j+h/4r1Gqnh9P/a6o05lFVQzsEMdgy67PD83slvLK/\n" +
            "o/ddILoo1sMrfakR8L5JVeQzHKDHAkAMfixWzOL3VFtc3s8epP78QI0L5hYQu1g3\n" +
            "QVTRTFy9wz00enNdfWoHv9xA/1Qb2CoULZj5blS164loDuspQkVtAkEAidvUb5Ya\n" +
            "L3Vktjk/zRb/dzdl10pFgtTFzjguyGyjAe/GxZbWcinpE1/wPMwzrRlUxYbpZSMZ\n" +
            "vQXI02AXTALWdA==";

    public static void main(String[] args) throws Exception {
//        String source = "{\n" +
//                "\t\"data\":\"1,2,3,45,5,6,7,7,8,121,2,3,45,5,6,7,7,8,12,22\",\n" +
//                "\t\"height\":123,\n" +
//                "\t\"age\":26,\n" +
//                "\t\"gender\":1\n" +
//                "}";// 要加密的字符串
//        System.out.println("准备用私钥加密的字符串为：" + source);
//
//        String cryptograph = privateEncrypt(source, PRIVATE_KEY);//私钥加密
//        System.out.print("用私钥加密后的结果为:" + cryptograph);
//        System.out.println();
//
//        String target = publicDecrypt(cryptograph, PUBLIC_KEY);//公钥解密
//        System.out.println("用公钥解密后的字符串为：" + target);
//        System.out.println();

        String aa = "ZwkxObs7zJF9uV0yPua16RuGdUx4SlS4k3B7PUXHhAZzmUq9KElff2TEJskeXtV5QfXvTaJwIXuixk08sUKVQ5eIssfiIocCmVrtua+uA5tnQihNN9QMfRgLrAzi7Hwtnbd9yK0TkAobavvxYyQ7jp0N32USNK1yyuB6J0Ax1uVzSAVICzJjeLV8bPjvEk2B/Oq3AGRakGl9f0KKXKHYWfcHFyWOgAgPZMOn0SYgT/guIm5zDgYvG9B98mBFDM3YNzmLF9sLyJJUW9Ck1eanFR9R6YAy8+ScPII/n1/z4qIqEPeGMfNQJ+M3FbjO7Pra+28vrpj35c10mQ06a9/XE3gtBqMBsXk0AiXaZEZeUvgASXz/otbgy777KPWisDQtGHalbCb+hZWU6kz61vDT/OLMUffHQsWakcfCASmtUwimSwugzQ0fDmml05E7NUWtEN4tNGdpOpdPcrtBxUeetS7dC1HmkWOqvuxfQEpnEZb7Y+m7yod5WtxNgS7Zj7YEOqu+fU0Lso5fwBq26NiKrMRVZDjKhxZvcqvRd+b1yCNVpV7/d0WOAYEeebhx3JB2ZCdjptsn5fNd+yaKGgqiqFekqb3tSuWJ8PQKVyZH+5xMCatic7/hRG9WMIwVnrVsMDa+LdlFt4IRjc9wPxVBj8IBdgaCb2Gtfyq/nJpPbqOaR4Qi18MMs0xLZiMe11Z/cOeNXmTQNbB0T5l9mT1f+Dh6e8vnrOuzWX0fFrmhyQY2eEwG1FE6pFCELHhKxnWXT0F8SjyQs/FYUs4qS3IaBAFfiqhgbrWpnqwoUnyRldRr/wrie6OydwZDmjv/gZtl5yAOlChq0ZD9/4j1doLJvZU0o339CZuhxGYM+Skgk27fqVGElnk3I+ZsjyHCF4WT80o+7VCQP6RvXoOFov5g8TJu5g89aL0N0lXGhOT47DGoei2msMnz9KAZ5ykoNX3ICJ6pYedctOAPPC5Y1fK/F52k7fqZo8EmOdzKFl6uJx/Tfy3VWpNqb4IG2HuQ0vm+a6xpsbIt/Jk/Q35PSLAPsynki0e1Yn7iFxbTpOIWU7bhGZib6VRV66HMnVBP9nXlD9UGrO0B90/j6qwqxSfFZ9VKEXBD21jUXLgQiztfobCKOb0JjA+alHWCkEBI+w4WA3bGT3tTzVtRuPyUVclLEH1+3lQuvEWQEK0t46rg4JkaxtbDNKAhHzdFUBdMu8XkPPKnAgXnengwo8HUMfCyXmOjFs/tzA8kkZZsdnrdxyj+Yw6sfBdwyzpZjobLXrTwlatKy66hjYKGkKNwfYwTQU3WvJ8t1qFTZBTockDu2K3WW5zMmffW66lumjzN1oJ3k2qhor4Z8XAYV3ZDauFRVnb64p4PxZMdIIb0HP8yXwsM+Jp7V8qgAYHYlhRBXJAhBXS50Q8nXvJDC0IKoyR8sqwNDiqBKTBaaHiTXQHW2N3iQH6kIEwmwmDfaF+J9FXc6rsDp+GRtCx1E78RASRC5sMbgLb5KexcdOmepk/W/16TWy1euXv0Y+lgesNIjend";
        String target = privateDecrypt(aa, PRIVATE_KEY);//私钥解密
        System.out.println("用私钥解密后的字符串为：" + target);
        System.out.println();
    }

    /**
     * 公钥加密方法
     *
     * @param source 明文
     * @return
     * @throws Exception
     */
    public static String publicEncrypt(String source, String pubKey) {
        String result = null;
        try {
            Key publicKey = getPublicKey(pubKey);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] b = source.getBytes();
            /** 执行加密操作 */
            BASE64Encoder encoder = new BASE64Encoder();
            result = encoder.encode(en(b, cipher));
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 私钥解密算法
     *
     * @param cryptograph 密文
     * @return
     * @throws Exception
     */
    public static String privateDecrypt(String cryptograph, String priKey) throws Exception {
        String result = null;
        try {
            Key privateKey = getPrivateKey(priKey);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b1 = decoder.decodeBuffer(cryptograph);
            result = de(b1, cipher);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 公钥解密方法
     *
     * @param cryptograph 密文
     * @return
     * @throws Exception
     */
    public static String publicDecrypt(String cryptograph, String pubKey) {
        String result = null;
        try {
            Key publicKey = getPublicKey(pubKey);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b1 = decoder.decodeBuffer(cryptograph);
            result = de(b1, cipher);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 私钥加密算法
     *
     * @param source 明文
     * @return
     * @throws Exception
     */
    public static String privateEncrypt(String source, String priKey) {
        String result = null;
        try {
            Key privateKey = getPrivateKey(priKey);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] b = source.getBytes();
            BASE64Encoder encoder = new BASE64Encoder();
            result = encoder.encode(en(b, cipher));
        } catch (Exception e) {
        }
        return result;
    }

    private static byte[] en(byte[] b, Cipher cipher) throws Exception {
        byte[] b1 = null;
        //加密时超过117字节采用分段加密
        if (b.length > 117) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < b.length; i += 117) {
                byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(b, i, i + 117));
                sb.append(new String(doFinal));
                b1 = ArrayUtils.addAll(b1, doFinal);
            }
        } else {
            b1 = cipher.doFinal(b);
        }
        return b1;
    }

    private static String de(byte[] b1, Cipher cipher) throws Exception {
        byte[] b = null;
        String resultData = null;
        //接密时超过128字节采用分段加密
        if (b1.length > 128) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < b1.length; i += 128) {
                byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(b1, i, i + 128));
                sb.append(new String(doFinal));
            }
            resultData = sb.toString();
        } else {
            b = cipher.doFinal(b1);
            resultData = new String(b);
        }
        return resultData;
    }

    private static PublicKey getPublicKey(String pubKey) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(pubKey));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        return publicKey;
    }

    private static PrivateKey getPrivateKey(String priKey) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(priKey));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        return privateKey;
    }
}
